import { Server as SocketIOServer, Socket } from 'socket.io';
import { Server as HttpServer } from 'http';
import { verifyToken } from './jwt';
import { logger } from './logger';
import { config } from '@/config';
import { redisUtils } from './redis';

export interface AuthenticatedSocket extends Socket {
  userId?: string;
  partnerId?: string;
}

// Socket.IO服务器实例
let io: SocketIOServer;

// 初始化Socket.IO服务器
export const initializeSocket = (server: HttpServer): SocketIOServer => {
  io = new SocketIOServer(server, {
    cors: {
      origin: config.ws.corsOrigin,
      methods: ['GET', 'POST'],
      credentials: true,
    },
    transports: ['websocket', 'polling'],
  });

  // 身份验证中间件
  io.use(async (socket: any, next) => {
    try {
      const token = socket.handshake.auth.token || socket.handshake.headers.authorization?.replace('Bearer ', '');
      
      if (!token) {
        return next(new Error('Authentication token required'));
      }

      const payload = verifyToken(token);
      socket.userId = payload.userId;
      
      // 获取用户的伙伴关系信息
      const partnerId = await redisUtils.get(`user:${payload.userId}:partner`);
      if (partnerId) {
        socket.partnerId = partnerId;
      }

      logger.info(`User ${payload.userId} connected to socket`);
      next();
    } catch (error) {
      logger.error('Socket authentication failed:', error);
      next(new Error('Authentication failed'));
    }
  });

  // 连接事件处理
  io.on('connection', (socket: AuthenticatedSocket) => {
    logger.info(`Socket connected: ${socket.id}, User: ${socket.userId}`);

    // 加入用户房间
    if (socket.userId) {
      socket.join(`user:${socket.userId}`);
      
      // 如果有伙伴关系，加入伙伴房间
      if (socket.partnerId) {
        socket.join(`partner:${socket.partnerId}`);
      }
      
      // 更新在线状态
      updateUserOnlineStatus(socket.userId, true);
    }

    // 消息事件
    socket.on('send_message', async (data) => {
      try {
        await handleSendMessage(socket, data);
      } catch (error) {
        logger.error('Failed to handle send_message:', error);
        socket.emit('error', { message: 'Failed to send message' });
      }
    });

    // 输入状态事件
    socket.on('typing_start', (data) => {
      if (socket.partnerId) {
        socket.to(`partner:${socket.partnerId}`).emit('user_typing', {
          userId: socket.userId,
          isTyping: true,
        });
      }
    });

    socket.on('typing_stop', (data) => {
      if (socket.partnerId) {
        socket.to(`partner:${socket.partnerId}`).emit('user_typing', {
          userId: socket.userId,
          isTyping: false,
        });
      }
    });

    // 游戏事件
    socket.on('join_game', async (data) => {
      try {
        await handleJoinGame(socket, data);
      } catch (error) {
        logger.error('Failed to handle join_game:', error);
        socket.emit('error', { message: 'Failed to join game' });
      }
    });

    socket.on('game_move', async (data) => {
      try {
        await handleGameMove(socket, data);
      } catch (error) {
        logger.error('Failed to handle game_move:', error);
        socket.emit('error', { message: 'Failed to make move' });
      }
    });

    // 断开连接事件
    socket.on('disconnect', () => {
      logger.info(`Socket disconnected: ${socket.id}, User: ${socket.userId}`);
      
      if (socket.userId) {
        // 更新离线状态
        updateUserOnlineStatus(socket.userId, false);
        
        // 通知伙伴用户离线
        if (socket.partnerId) {
          socket.to(`partner:${socket.partnerId}`).emit('user_offline', {
            userId: socket.userId,
          });
        }
      }
    });
  });

  return io;
};

// 处理发送消息
const handleSendMessage = async (socket: AuthenticatedSocket, data: any) => {
  const { content, type = 'text', receiverId } = data;
  
  if (!socket.userId || !socket.partnerId) {
    throw new Error('User not authenticated or not in a partner relationship');
  }

  // 这里应该调用消息服务来保存消息
  // const message = await messageService.createMessage({
  //   senderId: socket.userId,
  //   receiverId,
  //   partnerId: socket.partnerId,
  //   content,
  //   type,
  // });

  // 发送消息给伙伴房间
  io.to(`partner:${socket.partnerId}`).emit('new_message', {
    id: Date.now().toString(), // 临时ID
    senderId: socket.userId,
    receiverId,
    content,
    type,
    createdAt: new Date().toISOString(),
  });
};

// 处理加入游戏
const handleJoinGame = async (socket: AuthenticatedSocket, data: any) => {
  const { gameType, roomId } = data;
  
  if (!socket.userId) {
    throw new Error('User not authenticated');
  }

  // 加入游戏房间
  socket.join(`game:${roomId}`);
  
  // 通知房间内其他玩家
  socket.to(`game:${roomId}`).emit('player_joined', {
    userId: socket.userId,
    roomId,
  });
};

// 处理游戏移动
const handleGameMove = async (socket: AuthenticatedSocket, data: any) => {
  const { roomId, move } = data;
  
  if (!socket.userId) {
    throw new Error('User not authenticated');
  }

  // 这里应该调用游戏服务来处理移动
  // const gameState = await gameService.makeMove(roomId, socket.userId, move);

  // 广播移动给房间内所有玩家
  io.to(`game:${roomId}`).emit('game_move', {
    userId: socket.userId,
    move,
    // gameState,
  });
};

// 更新用户在线状态
const updateUserOnlineStatus = async (userId: string, isOnline: boolean) => {
  try {
    if (isOnline) {
      await redisUtils.set(`user:${userId}:online`, 'true', 300); // 5分钟过期
    } else {
      await redisUtils.del(`user:${userId}:online`);
    }
  } catch (error) {
    logger.error('Failed to update user online status:', error);
  }
};

// 获取Socket.IO实例
export const getSocketIO = (): SocketIOServer => {
  if (!io) {
    throw new Error('Socket.IO not initialized');
  }
  return io;
};

// 发送通知给特定用户
export const sendNotificationToUser = (userId: string, notification: any) => {
  if (io) {
    io.to(`user:${userId}`).emit('notification', notification);
  }
};

// 发送消息给伙伴
export const sendMessageToPartner = (partnerId: string, message: any) => {
  if (io) {
    io.to(`partner:${partnerId}`).emit('new_message', message);
  }
};